﻿using System.Collections.Generic;
using System.Linq;

namespace VPLink2014.Data.MesApplis
{
	public class VOServiceMapper : VOTeamMapper
	{
		public VOService service;
		public VOServiceMapper()
			: base()
		{
		}
		public VOServiceMapper( string name ):base()
		{
            using (VPLinkLogConnection db = new VPLinkLogConnection())
			{
				service = ( from u in db.VplinkEntities.Services
						  where u.nom == name
						  select new VOService() { Id = u.id, Name = u.nom } ).FirstOrDefault();
			}
		}

		private List<User> GetUsersWithApplis( List<VOApplication> applications )
		{
			List<User> dbUsersFromService = new List<User>();
            using (VPLinkLogConnection db = new VPLinkLogConnection())
			{
				dbUsersFromService = (from User usr in db.VplinkEntities.Users 
										from Service sce in db.VplinkEntities.Services 
										from AppliUser appliUser in db.VplinkEntities.AppliServices
										where usr.Service == sce.nom
										where usr.LoginUser == appliUser.user 
										select usr).ToList<User>();
			}
			return dbUsersFromService;
		}
		public override void SetApplications( List<VOApplication> applications )
		{
			using( VPLinkLogConnection db = new VPLinkLogConnection() )
			{
				Service serviceDb = ( from Service sce in db.VplinkEntities.Services
									   where sce.id == service.Id
									   select sce ).FirstOrDefault<Service>();

				// Deleted Apps
				List<AppliService> deletedApps = serviceDb.AppliServices.Where( i => !applications.Select( x => x.Id ).Contains( i.appli ) ).ToList<AppliService>();
                deletedApps.ForEach(x => db.VplinkEntities.AppliServices.Remove(x));

				//Delete from users Db
				
				
				List<User> usersWithApplisFromServiceDb = ( from User usr in db.VplinkEntities.Users
															 from AppliUser appliUser in db.VplinkEntities.AppliUsers
															 where usr.Service == this.service.Name
															 where usr.LoginUser == appliUser.user
															 select usr ).Distinct().ToList<User>();
				
				foreach( User user in usersWithApplisFromServiceDb )
				{
                    //user.AppliUsers.Load();
					List<AppliUser> specificUserApps = user.AppliUsers
						.Where( i => !applications.Select( x => x.Id ).Contains( i.appli ) )
						.OrderBy( x => x.rang ).ToList<AppliUser>();
					for( int i = 0; i < specificUserApps.Count(); i++ )
					{
						specificUserApps[i].rang = applications.Count() + i + 1;
					}
					if( deletedApps.Count() > 0 )
					{
						List<AppliUser> deletedUserApps = user.AppliUsers.Where( i => deletedApps.Select( x => x.appli ).Contains( i.appli ) ).ToList<AppliUser>();
                        deletedUserApps.ForEach(x => db.VplinkEntities.AppliUsers.Remove(x));
					}
				}
				foreach( VOApplication application in applications )
				{
					Application appliDb = ( from Application appli in db.VplinkEntities.Applications
											 where appli.id == application.Id
											 select appli ).FirstOrDefault<Application>();

					UpdateUsers( db, usersWithApplisFromServiceDb, application, appliDb );
					UpdateTeamApplis( db, serviceDb, application, appliDb );
				}
			}
		}

		private void UpdateTeamApplis( VPLinkLogConnection db, Service serviceDb, VOApplication application, Application appliDb )
		{
			AppliService appliDepts = ( from AppliService sce in db.VplinkEntities.AppliServices
									 where sce.service == service.Id
									 where sce.appli == application.Id
									 select sce ).FirstOrDefault<AppliService>();
			// Add New
			if( appliDepts == null )
			{
				AppliService newAppliSce = new AppliService()
				{
					Service1 = serviceDb,
					Application = appliDb,
					service = this.service.Id,
					appli = application.Id,
					rang = application.Rang,
					obligatoire = application.Obligatoire
				};
				db.VplinkEntities.AppliServices.Add( newAppliSce );
			}
			else
			{
				// Update existing
				appliDepts.obligatoire = application.Obligatoire;
				appliDepts.rang = application.Rang;
			}
		}

		private static void UpdateUsers( VPLinkLogConnection db, List<User> usersWithApplisFromServiceDb, VOApplication application, Application appliDb )
		{
			foreach( User user in usersWithApplisFromServiceDb )
			{
				AppliUser appliUser = ( from AppliUser usrAppli in db.VplinkEntities.AppliUsers
										where usrAppli.appli == application.Id
										where usrAppli.user == user.LoginUser
										select usrAppli ).FirstOrDefault();

				if( appliUser == null )
				{
					db.VplinkEntities.AppliUsers.Add( new AppliUser()
					{
						appli = application.Id,
						user = user.LoginUser,
						User1 = user,
						Application = appliDb,
						obligatoire = application.Obligatoire,
						rang = application.Rang
					} );
				}
				else
				{
					appliUser.obligatoire = application.Obligatoire;
					appliUser.rang = application.Rang;
				}
			}
		}

		
		public override List<VOApplication> GetApplicationsTeam()
		{
			List<VOApplication> applicationsByService = new List<VOApplication>();
			using( VPLinkLogConnection db = new VPLinkLogConnection() )
			{
				applicationsByService = (
										from appliSce in db.VplinkEntities.AppliServices
										from applis in db.VplinkEntities.Applications
										from sces in db.VplinkEntities.Services
										where sces.nom == this.service.Name
										where applis.id == appliSce.appli
										where sces.id == appliSce.service
										orderby appliSce.rang
										select new VOApplication() { 
											Id = applis.id, 
											Url = applis.url, 
											Name = applis.titre, 
											Categorie = string.IsNullOrEmpty( applis.categorie ) ? "Autre" : applis.categorie, 
											Description = applis.description, 
											Obligatoire = appliSce.obligatoire, 
											Rang = appliSce.rang 
										} ).ToList<VOApplication>();
			}
			return applicationsByService;
		}
	}
}
